﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Api.index;
namespace Api.searcher
{
    internal class DocSearcher
    {
       
        public DocSearcher()
        {
            
        }

        public List<Result> search(string query)
        {
            // 1.【分词】针对 query 查询词进行分词
            IEnumerable<string> terms = index.Index.index.Divide(query);
            
            // 2.【触发】针对分词结果来查倒排
            List<Weight> allTermResult = new List<Weight>();
            foreach (string term in terms)
            {
                string word = term;
                List<Weight> invertedList = index.Index.index.getInverted(word);
                if (invertedList == null)
                {
                    // 说明这个查询词在所有文档中都不存在
                    continue;
                }
                allTermResult.AddRange(invertedList);
            }
           
            // 3.【排序】针对触发结果按照权重降序排序
            allTermResult.Sort((a, b) => -a.getWeight().CompareTo(b.getWeight()));
            foreach (Weight term in allTermResult)
            {
                Console.WriteLine(term.getWeight());
                Console.WriteLine(term.getDocId());
            }
            
            
            // 4.【包装结果】针对排序的结果，查正排，构造出要返回的数据
            List<Result> results = new List<Result>();
            foreach (Weight weight in allTermResult)
            {
                //System.out.println(weight.getDocId());
                DocInfo docInfo = index.Index.index.getDocInfo(weight.getDocId());
                
                //System.out.println(docInfo.getUrl());
                Result result = new Result();
                result.setTitle(docInfo.getTitle());
                result.setUrl(docInfo.getUrl());
                result.setDesc(GenDesc(docInfo.getContent(), terms));
                results.Add(result);
            }
            
            return results;
        }
        private string GenDesc(string content, IEnumerable<string> terms)
        {
            // 先遍历分词结果，看看哪个结果在 content 中存在
            int firstPos = -1;
            foreach  (string term in terms)
            {
                // 分词库直接针对词进行转小写了
                // 正因为如此，就必须把正文内容也先转为小写，然后再查询
                string word = term;
                // 此处需要的是 “全字匹配” ，让 word 能够独立成词，才要查找出来，而不是只作为词的一部分
                // 此处的 “全字匹配” 的实现不算特别严谨，更严谨的做法，可以使用正则表达式
                firstPos = content.ToLower().IndexOf(" " + word + " ");
                if (firstPos >= 0)
                {
                    // 找到了位置
                    break;
                }
            }
            if (firstPos == -1)
            {
                // 所有的分词结果都不在正文中
                // 属于比较极端的情况
                // 可以直接读取正文的前160字符作为描述
                if (content.Length > 160)
                {
                    return content.Substring(0, 160) + "...";
                }
                return content;
            }
            // 从 firstPos 作为基准，往前找 60 个字符，作为描述的起始位置
            string desc = "";
            int descBeg = firstPos > 60 ? firstPos - 60 : 0;
            if (descBeg + 160 > content.Length)
            {
                desc = content.Substring(descBeg);
            }
            else
            {
                desc = content.Substring(descBeg, descBeg + 160) + "...";
            }
            return desc;
        }
    }
}
